package top.codef.secure.filters;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.web.filter.OncePerRequestFilter;

import com.fasterxml.jackson.databind.ObjectMapper;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import top.codef.secure.interfaces.CaptchaRepository;
import top.codef.secure.pojomodel.SecureResponseEnum;

public class CaptchaFilter extends OncePerRequestFilter {

	private final CaptchaRepository captchaRepository;

	private Set<RequestMatcher> captchaRequestMatcher = new HashSet<>();

	private Log logger = LogFactory.getLog(getClass());

	private final ObjectMapper objectMapper;

	public CaptchaFilter(CaptchaRepository captchaRepository, ObjectMapper objectMapper, String... requestUris) {
		this.captchaRepository = captchaRepository;
		this.objectMapper = objectMapper;
		for (String requestUri : requestUris)
			captchaRequestMatcher.add(new AntPathRequestMatcher(requestUri));
	}

	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
			throws ServletException, IOException {
		if (match(request)) {
			boolean check = captchaRepository.check(request);
			logger.debug("captcha验证结果：" + check);
			if (!check) {
				logger.debug("人机验证失败");
				response.setContentType("application/json; charset=utf-8");
				response.setStatus(SecureResponseEnum.LOGIN_CAPTCHA_FAILED.getHttpStatus().value());
				response.getWriter().write(
						objectMapper.writeValueAsString(SecureResponseEnum.LOGIN_CAPTCHA_FAILED.createSecureModel()));
				request.getSession().invalidate();
				return;
			}
		}
		filterChain.doFilter(request, response);
	}

	private boolean match(HttpServletRequest request) {
		for (RequestMatcher requestMatcher : captchaRequestMatcher) {
			if (requestMatcher.matches(request))
				return true;
		}
		return false;
	}
}
